#include "ComplexOrderLoader.h"

ComplexOrderLoader::ComplexOrderLoader(const QString &user, const QString &passwd, const QString& filename, uint bufferCapacity)
    : BaseLoader(user, passwd, bufferCapacity)
    , _collectorData(new SimpleCollectorData(filename))
{   
    if (!_sqlQuery.exec("use dbcomplexorder;") || !_sqlQuery.exec("CALL cleanDatabase;")) {
        cout << "Nao foi possivel limpar o conteudo do banco de dados" << endl;
        cout << _sqlQuery.lastError().text().toStdString() << endl;
        throw -1;
    }
}

ComplexOrderLoader::~ComplexOrderLoader()
{
    delete _collectorData;
}

QString ComplexOrderLoader::serialize(EdgeElement& e) const
{
    // http://dev.mysql.com/doc/refman/5.0/en/string-syntax.html
    e.value.replace("\\","\\\\");
    e.value.replace("\'","\\\'");
    e.value.replace("\"","\\\"");

    QString line("(");
    line.append(QString().setNum(e.id).append(","));        // id
    line.append(QString().setNum(e.order).append(","));     // order
    line.append(QString().setNum(e.size).append(","));      // size
    if (e.parent_id == 0)                                   // parent_id
        line.append("NULL,");
    else
        line.append(QString().setNum(e.parent_id).append(","));
    line.append(QString().setNum(e.path_id).append(","));   // path_id
//    if (e.end_desc_id != e.id)                              // end_desc_id
        line.append(QString().setNum(e.end_desc_id).append(","));
//    else
//        line.append("NULL,");
    if (e.value.isEmpty())                                  // value
        line.append("NULL,");
    else
        line.append(QString("\"").append(e.value).append("\","));
    if (e.attribute)                                        // attribute
        line.append("1");
    else
        line.append("0");

    line.append("),");

    return line;
}

EdgeElement* ComplexOrderLoader::newElement(EdgeElement* parent, uint id, const QString& value, uint path_id, bool attribute) const
{
    EdgeElement* element = new EdgeElement();
    element->id = id;
    element->path_id = path_id;

    if (parent) {
        // pega os dados do pai
        QMap<uint,SimpleEdgeElement*>::iterator it = _collectorData->getData().find(parent->id);
        if (it == _collectorData->getData().end())
            cout << "Erro grave aqui! Não encontrou o índice no mapa previamente calculado" << endl;
        SimpleEdgeElement* dataElement = it.value();

        uint num_intervals = dataElement->num_children * 2 + 1;
        uint interval_size = (parent->size-1) / num_intervals;

        /**
         *  a ordem do elemento é a ordem do pai mais um deslocamento que depende
         *  do número de filhos, e o tamanho do intervalo é o intervalo do pai
         *  dividido pelo número de filhos, de forma a gerar intervalos vazios
         *  antes e depois do elemento
         */
        element->order = parent->order + 1 + (parent->num_children * 2 + 1) * interval_size;
        element->size = interval_size;

        element->parent_id = parent->id;
//        parent->end_desc_id = element->id;
        parent->num_children++;
    } else {
        // é raiz
        element->order = 0;
        element->size = MAX_INT;
        element->parent_id = 0;
        element->end_desc_id = element->id;
    }
    element->value = value;
    element->attribute = attribute;

    return element;
}
